use std::ops::Add;
use chrono::{DateTime, Duration, FixedOffset, Local, NaiveDateTime, Utc};

const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
const FORMAT_M: &str = "%Y-%m-%d %H:%M:%S%.3f";

pub fn format_time(time: &DateTime<Local>) -> String {
    format!("{}", time.format(FORMAT))
}

pub fn format_time3(time: &Option<DateTime<Local>>) -> String {
    match time {
        Some(time) => {format!("{}", time.format(FORMAT))}
        None => {String::from("")}
    }
}

pub fn format_time2(time: &DateTime<Utc>) -> String {
    format!("{}", time.format(FORMAT))
}

pub fn format_time_m(time: &DateTime<Local>) -> String {
    format!("{}", time.format(FORMAT_M))
}

pub fn format_time_m3(time: &Option<DateTime<Local>>) -> String {
    log::info!("format time m3, {:?}", time);
    match time {
        Some(time) => {format!("{}", time.format(FORMAT_M))}
        None => {String::from("")}
    }
}

pub fn parse_to_time(time: String) -> DateTime<Local> {
    log::info!("parse time: {}", time);
    
    let t = NaiveDateTime::parse_from_str(&time, FORMAT);
    let tz = FixedOffset::east_opt(8 * 3600).unwrap();
    match t { 
        Ok(t) => t.and_local_timezone(tz).unwrap().with_timezone(&Local),
        Err(e) => {
            log::error!("parse time: {}", e);
            Local::now()
        },
    }
}

pub fn parse_to_time_m(time: String) -> DateTime<Local> {
    log::info!("parse time2: {}", time);

    let t = NaiveDateTime::parse_from_str(&time, FORMAT_M);
    let tz = FixedOffset::east_opt(8 * 3600).unwrap();
    match t {
        Ok(t) => t.and_local_timezone(tz).unwrap().with_timezone(&Local),
        Err(e) => {
            log::error!("parse time: {}", time);
            log::error!("parse time: {}", e);
            Local::now()
        },
    }
}

pub fn format_time_by_format(time: &DateTime<Local>, format: &'static str) -> String {
    format!("{}", time.format(format))
}

pub fn parse_to_time_by_format(time: &String, format: &'static str) -> Option<DateTime<Local>> {
    log::info!("parse time: {}", time);

    let t = NaiveDateTime::parse_from_str(time, format);
    let tz = FixedOffset::east_opt(8 * 3600).unwrap();
    match t {
        Ok(t) => Some(t.and_local_timezone(tz).unwrap().with_timezone(&Local)),
        Err(e) => {
            log::info!("parse time: {}", e);
            None
        },
    }
}

pub fn format_session_time(date_time: &DateTime<Local>)->String {
    let today = Local::now().date_naive();
    let d = date_time.date_naive();
    if today == d {
        return format_time_by_format(&date_time,"%H:%M");
    }
    let yesterday = today - Duration::days(1);
    if yesterday == d {
        return "昨天".to_string();
    }

    let before_day = today - Duration::days(2);
    if before_day == d {
        return "前天".to_string();
    }

    return format_time_by_format(&date_time,"%Y-%m-%d");
}

pub fn has_exceeded_time(date_time: &DateTime<Local>, send_time: i32) -> bool {
    date_time.add(Duration::minutes(send_time as i64)).gt(&Local::now())
}